package vashion.azeroth.core.service.es.impl;

import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import vashion.azeroth.core.es.pojo.Item;
import vashion.azeroth.core.es.repository.ItemRepository;
import vashion.azeroth.core.service.es.ItemESService;
import vashion.azeroth.core.service.es.query.ItemQuery;

@Service
public class ItemESServiceImpl implements ItemESService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ItemESServiceImpl.class);

    /* 搜索模式 */
    String SCORE_MODE_SUM = "sum"; // 权重分求和模式
    Float  MIN_SCORE = 10.0F;      // 由于无相关性的分值默认为 1 ，设置权重分最小值为 10
    
    @Autowired
    ItemRepository itemRepository;
    
    public Long saveItem(Item item) {
        Item itemResult = itemRepository.save(item);
        return itemResult.getId();
    }
    
    @Override
    public Page<Item> searchItem(ItemQuery itemQuery) {

        LOGGER.info("\n searchCity: searchContent [" + itemQuery.getSearchContent() + "] \n ");
        // 构建搜索查询
        SearchQuery searchQuery = getCitySearchQuery(itemQuery);
        LOGGER.info("\n searchCity: searchContent [" + itemQuery.getSearchContent() + "] \n DSL  = \n " + searchQuery.getQuery().toString());
        Page<Item> itemPage = itemRepository.search(searchQuery);
        return itemPage;
    }
    
    @Override
    public Page<Item> searchMutiItem(ItemQuery itemQuery) {
        LOGGER.info("\n searchCity: searchContent [" + itemQuery.getSearchContent() + "] \n ");
        // 构建搜索查询
        SearchQuery searchQuery = getCityMutiSearchQuery(itemQuery);
        LOGGER.info("\n searchCity: searchContent [" + itemQuery.getSearchContent() + "] \n DSL  = \n " + searchQuery.getQuery().toString());
        
        Page<Item> itemPage = itemRepository.search(searchQuery);
        return itemPage;
    } 
    
    /**
     * 根据搜索词构造搜索查询语句
     *
     * 代码流程：
     *      - 权重分查询
     *      - 短语匹配
     *      - 设置权重分最小值
     *      - 设置分页参数
     *
     * @param pageNumber 当前页码
     * @param pageSize 每页大小
     * @param searchContent 搜索内容
     * @return
     */
    private SearchQuery getCitySearchQuery(ItemQuery itemQuery) {
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchPhraseQuery("tag", itemQuery.getSearchContent()),
                ScoreFunctionBuilders.weightFactorFunction(1000))
                .add(QueryBuilders.matchPhraseQuery("brandTitle", itemQuery.getSearchContent()),
                ScoreFunctionBuilders.weightFactorFunction(500))
                .add(QueryBuilders.matchPhraseQuery("itemDesc", itemQuery.getSearchContent()),
                ScoreFunctionBuilders.weightFactorFunction(500))
                .scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE);
        
        return new NativeSearchQueryBuilder()
                .withPageable(itemQuery.getPageable())
                .withQuery(functionScoreQueryBuilder).build();
    }
    
    private SearchQuery getCityMutiSearchQuery(ItemQuery itemQuery) {
        
        MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery(itemQuery.getSearchContent(), "tag","brandTitle","itemDesc");  
        
        return new NativeSearchQueryBuilder()
                .withPageable(itemQuery.getPageable())
                .withQuery(query).build();
    }
}
